Skip to main content

Positions

Understand how to manage and monitor asset positions in your trading portfolio.

Overview​

Positions represent your holdings of different assets. The framework automatically tracks positions as orders are executed, providing real-time visibility into your portfolio composition and performance.

Understanding Positions​

What is a Position?​

A position represents:

  • Symbol: The trading pair (e.g., "BTC/USDT")
  • Amount: Quantity of the asset held
  • Entry Price: Average price at which the position was acquired
  • Current Value: Current market value of the position
  • Unrealized P&L: Profit/loss since opening the position

Position Lifecycle​

  1. Opening: Position created when you first buy an asset
  2. Scaling: Position size changes as you buy or sell more
  3. Closing: Position removed when you sell all holdings

Accessing Positions​

Get All Positions​

def apply_strategy(self, algorithm, market_data):
# Get all current positions
positions = algorithm.get_positions()

for position in positions:
print(f"Position: {position.symbol}")
print(f"Amount: {position.amount}")

Get Specific Position​

def apply_strategy(self, algorithm, market_data):
# Get position for specific symbol
btc_position = algorithm.get_position("BTC")

if btc_position:
print(f"BTC Position: {btc_position.amount} BTC")
else:
print("No BTC position")

Position Properties​

def analyze_position(self, position, market_data):
# Basic properties
symbol = position.symbol
amount = position.amount
entry_price = position.entry_price

# Current market data
current_price = market_data.get_last_price(symbol)

# Calculated metrics
current_value = position.current_value
unrealized_pnl = current_value - (amount * entry_price)
pnl_percentage = (unrealized_pnl / (amount * entry_price)) * 100

print(f"Symbol: {symbol}")
print(f"Amount: {amount}")

Position Management Strategies​

Multi-Symbol Strategy Allocation

When trading multiple symbols simultaneously, ensure your total position size allocations don't exceed 100% of your portfolio. The framework will automatically scale orders proportionally if needed, but it's best practice to plan allocations that fit within available funds (e.g., 5 symbols × 20% = 100%).

Profit Taking​

class ProfitTakingStrategy(TradingStrategy):

def __init__(self, profit_target=0.10):
super().__init__()
self.profit_target = profit_target

def apply_strategy(self, algorithm, market_data):
positions = algorithm.get_positions()

for position in positions:
current_price = market_data.get_last_price(position.symbol)

# Calculate profit percentage
profit_pct = (current_price - position.entry_price) / position.entry_price

if profit_pct >= self.profit_target:
# Take profits - sell 50% of position
target_symbol = position.symbol.split('/')[0] # Extract base symbol
algorithm.create_sell_order(
target_symbol=target_symbol,
percentage=0.5,
order_type="MARKET"
)
print(f"Taking profits on {position.symbol}")

Stop Loss Management​

class StopLossStrategy(TradingStrategy):

def __init__(self, stop_loss_pct=0.05):
super().__init__()
self.stop_loss_pct = stop_loss_pct

def apply_strategy(self, algorithm, market_data):
positions = algorithm.get_positions()

for position in positions:
current_price = market_data.get_last_price(position.symbol)

# Calculate loss percentage
loss_pct = (position.entry_price - current_price) / position.entry_price

if loss_pct >= self.stop_loss_pct:
# Stop loss triggered - sell entire position
target_symbol = position.symbol.split('/')[0]
algorithm.create_sell_order(
target_symbol=target_symbol,
percentage=1.0,
order_type="MARKET"
)
print(f"Stop loss triggered for {position.symbol}")

Position Sizing​

The framework provides a PositionSize class to define how much capital to allocate to each symbol. You can specify either a percentage of portfolio or a fixed amount.

from investing_algorithm_framework import TradingStrategy, PositionSize, TimeUnit

class MultiAssetStrategy(TradingStrategy):
time_unit = TimeUnit.HOUR
interval = 2
symbols = ["BTC", "ETH", "SOL", "ADA", "XRP"]

# Define position sizes for each symbol
position_sizes = [
PositionSize(symbol="BTC", percentage_of_portfolio=20.0),
PositionSize(symbol="ETH", percentage_of_portfolio=20.0),
PositionSize(symbol="SOL", percentage_of_portfolio=20.0),
PositionSize(symbol="ADA", percentage_of_portfolio=20.0),
PositionSize(symbol="XRP", percentage_of_portfolio=20.0),
]

Fixed Amount vs Percentage​

# Percentage-based: allocates 20% of total portfolio value
PositionSize(symbol="BTC", percentage_of_portfolio=20.0)

# Fixed amount: always allocates exactly 500 EUR
PositionSize(symbol="ETH", fixed_amount=500.0)

Proportional Scaling​

When multiple buy signals fire simultaneously and the total requested allocation exceeds available funds, the framework automatically scales all orders proportionally to ensure fair allocation across all symbols.

Example:

  • Portfolio: 1000 EUR available
  • 5 symbols each want 20% = 200 EUR each = 1000 EUR total
  • If only 800 EUR is available, each order is scaled to 160 EUR (80% of requested)

This behavior ensures:

  • Fair allocation: All symbols get the same percentage reduction
  • Predictable results: Order of symbols doesn't affect allocation
  • No failures: Orders are scaled rather than rejected
# If total allocation exceeds available funds, you'll see a warning:
# "Total allocation (1000.00) exceeds available funds (800.00).
# Scaling all orders by 80.00% to maintain proportional allocation."

Rebalancing Example​

class PositionSizingStrategy(TradingStrategy):

def __init__(self, max_position_size=0.1):
super().__init__()
self.max_position_size = max_position_size

def apply_strategy(self, algorithm, market_data):
portfolio = algorithm.get_portfolio()
positions = algorithm.get_positions()

# Check if any position exceeds maximum size
total_portfolio_value = portfolio.get_total_value()

for position in positions:
position_weight = position.current_value / total_portfolio_value

if position_weight > self.max_position_size:
# Position too large - reduce it
target_weight = self.max_position_size * 0.9 # Reduce to 90% of max
target_value = total_portfolio_value * target_weight
excess_value = position.current_value - target_value

# Calculate percentage to sell
sell_percentage = excess_value / position.current_value

target_symbol = position.symbol.split('/')[0]
algorithm.create_sell_order(
target_symbol=target_symbol,
percentage=sell_percentage,
order_type="MARKET"
)
print(f"Reducing oversized position in {position.symbol}")

Position Analytics​

Portfolio Composition​

def analyze_portfolio_composition(self, algorithm):
positions = algorithm.get_positions()
portfolio = algorithm.get_portfolio()
total_value = portfolio.get_total_value()

print("Portfolio Composition:")
print("-" * 40)

for position in positions:
weight = (position.current_value / total_value) * 100
print(f"{position.symbol}: {weight:.2f}%")

# Check for cash position
cash = portfolio.get_unallocated()
cash_weight = (cash / total_value) * 100
print(f"Cash: {cash_weight:.2f}%")

Performance Tracking​

def track_position_performance(self, positions, market_data):
total_unrealized_pnl = 0

print("Position Performance:")
print("-" * 60)

for position in positions:
current_price = market_data.get_last_price(position.symbol)

# Calculate metrics
cost_basis = position.amount * position.entry_price
current_value = position.amount * current_price
unrealized_pnl = current_value - cost_basis
pnl_percentage = (unrealized_pnl / cost_basis) * 100

total_unrealized_pnl += unrealized_pnl

print(f"{position.symbol:10} | "
f"Amount: {position.amount:8.4f} | "
f"P&L: ${unrealized_pnl:8.2f} ({pnl_percentage:6.2f}%)")

print("-" * 60)
print(f"Total Unrealized P&L: ${total_unrealized_pnl:.2f}")

Risk Management​

Position Limits​

class PositionLimitStrategy(TradingStrategy):

def __init__(self, max_positions=5):
super().__init__()
self.max_positions = max_positions

def apply_strategy(self, algorithm, market_data):
positions = algorithm.get_positions()

# Check if we can open new positions
if len(positions) >= self.max_positions:
print(f"Maximum positions ({self.max_positions}) reached")
return

# Strategy logic for opening new positions
self.look_for_entry_signals(algorithm, market_data)

Correlation Management​

class CorrelationStrategy(TradingStrategy):

def check_position_correlation(self, algorithm, new_symbol):
"""Check if new position would create too much correlation"""
positions = algorithm.get_positions()

# Define highly correlated pairs
correlations = {
"BTC/USDT": ["ETH/USDT", "LTC/USDT"],
"ETH/USDT": ["BTC/USDT", "ADA/USDT"],
# Add more correlations
}

correlated_symbols = correlations.get(new_symbol, [])

# Check if we already hold correlated assets
existing_symbols = [pos.symbol for pos in positions]

for existing in existing_symbols:
if existing in correlated_symbols:
print(f"Warning: {new_symbol} is correlated with existing position {existing}")
return False

return True

Advanced Position Features​

Position Averaging​

class AveragingStrategy(TradingStrategy):

def apply_strategy(self, algorithm, market_data):
symbol = "BTC/USDT"
position = algorithm.get_position(symbol)
current_price = market_data.get_last_price(symbol)

if position:
# Calculate if we should average down
if current_price < position.entry_price * 0.95: # 5% below entry
# Buy more to average down
algorithm.create_buy_order(
target_symbol="BTC",
amount=100,
order_type="MARKET"
)
print(f"Averaging down BTC position")

Position Scaling​

class ScalingStrategy(TradingStrategy):

def apply_strategy(self, algorithm, market_data):
symbol = "BTC/USDT"
position = algorithm.get_position(symbol)
current_price = market_data.get_last_price(symbol)

if position:
profit_pct = (current_price - position.entry_price) / position.entry_price

# Scale out profits at different levels
if profit_pct >= 0.20: # 20% profit
algorithm.create_sell_order(
target_symbol="BTC",
percentage=0.25, # Sell 25%
order_type="MARKET"
)
elif profit_pct >= 0.10: # 10% profit
algorithm.create_sell_order(
target_symbol="BTC",
percentage=0.15, # Sell 15%
order_type="MARKET"
)

Best Practices​

1. Regular Position Review​

def review_positions_daily(self, algorithm, market_data):
"""Daily position review routine"""
positions = algorithm.get_positions()

for position in positions:
# Check for stale positions
if position.days_held > 30:
print(f"Long-term position: {position.symbol}")

# Check performance
current_price = market_data.get_last_price(position.symbol)
pnl_pct = (current_price - position.entry_price) / position.entry_price

if pnl_pct < -0.10: # More than 10% loss
print(f"Underperforming position: {position.symbol} ({pnl_pct:.2%})")

2. Position Documentation​

class DocumentedStrategy(TradingStrategy):

def __init__(self):
super().__init__()
self.position_notes = {}

def open_position_with_reason(self, algorithm, symbol, amount, reason):
"""Document why we're opening a position"""
algorithm.create_buy_order(
target_symbol=symbol,
amount=amount,
order_type="MARKET"
)

self.position_notes[symbol] = {
'reason': reason,
'date': datetime.now(),
'entry_price': market_data.get_last_price(f"{symbol}/USDT")
}

3. Position Monitoring​

Set up alerts and monitoring for your positions:

def monitor_positions(self, algorithm, market_data):
"""Monitor positions for alerts"""
positions = algorithm.get_positions()

for position in positions:
current_price = market_data.get_last_price(position.symbol)
pnl_pct = (current_price - position.entry_price) / position.entry_price

# Alert conditions
if pnl_pct > 0.50: # 50% profit
print(f"🎉 Big winner! {position.symbol} up {pnl_pct:.1%}")

elif pnl_pct < -0.15: # 15% loss
print(f"⚠️ Large loss! {position.symbol} down {pnl_pct:.1%}")

Next Steps​

Learn about Trades to understand how individual transactions create and modify positions over time.